/*
 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
 * Released under the terms of the GNU GPL v2.0.
 */

#include <qlistview.h>
#if QT_VERSION >= 300
#include <qsettings.h>
#else
class QSettings {
   public:
    void beginGroup(const QString &group) {}
    void endGroup(void) {}
    bool readBoolEntry(const QString &key, bool def = FALSE, bool *ok = 0) const {
        if (ok) *ok = FALSE;
        return def;
    }
    int readNumEntry(const QString &key, int def = 0, bool *ok = 0) const {
        if (ok) *ok = FALSE;
        return def;
    }
    QString readEntry(const QString &key, const QString &def = QString::null, bool *ok = 0) const {
        if (ok) *ok = FALSE;
        return def;
    }
    QStringList readListEntry(const QString &key, bool *ok = 0) const {
        if (ok) *ok = FALSE;
        return QStringList();
    }
    template <class t>
    bool writeEntry(const QString &key, t value) {
        return TRUE;
    }
};
#endif

class ConfigView;
class ConfigList;
class ConfigItem;
class ConfigLineEdit;
class ConfigMainWindow;

class ConfigSettings : public QSettings {
   public:
    QValueList<int> readSizes(const QString &key, bool *ok);
    bool writeSizes(const QString &key, const QValueList<int> &value);
};

enum colIdx { promptColIdx, nameColIdx, noColIdx, modColIdx, yesColIdx, dataColIdx, colNr };
enum listMode { singleMode, menuMode, symbolMode, fullMode, listMode };

class ConfigList : public QListView {
    Q_OBJECT
    typedef class QListView Parent;

   public:
    ConfigList(ConfigView *p, const char *name = 0);
    void reinit(void);
    ConfigView *parent(void) const {
        return (ConfigView *)Parent::parent();
    }
    ConfigItem *findConfigItem(struct menu *);

   protected:
    void keyPressEvent(QKeyEvent *e);
    void contentsMousePressEvent(QMouseEvent *e);
    void contentsMouseReleaseEvent(QMouseEvent *e);
    void contentsMouseMoveEvent(QMouseEvent *e);
    void contentsMouseDoubleClickEvent(QMouseEvent *e);
    void focusInEvent(QFocusEvent *e);
    void contextMenuEvent(QContextMenuEvent *e);

   public slots:
    void setRootMenu(struct menu *menu);

    void updateList(ConfigItem *item);
    void setValue(ConfigItem *item, tristate val);
    void changeValue(ConfigItem *item);
    void updateSelection(void);
    void saveSettings(void);
   signals:
    void menuChanged(struct menu *menu);
    void menuSelected(struct menu *menu);
    void parentSelected(void);
    void gotFocus(struct menu *);

   public:
    void updateListAll(void) {
        updateAll = true;
        updateList(NULL);
        updateAll = false;
    }
    ConfigList *listView() {
        return this;
    }
    ConfigItem *firstChild() const {
        return (ConfigItem *)Parent::firstChild();
    }
    int mapIdx(colIdx idx) {
        return colMap[idx];
    }
    void addColumn(colIdx idx, const QString &label) {
        colMap[idx] = Parent::addColumn(label);
        colRevMap[colMap[idx]] = idx;
    }
    void removeColumn(colIdx idx) {
        int col = colMap[idx];
        if (col >= 0) {
            Parent::removeColumn(col);
            colRevMap[col] = colMap[idx] = -1;
        }
    }
    void setAllOpen(bool open);
    void setParentMenu(void);

    template <class P>
    void updateMenuList(P *, struct menu *);

    bool updateAll;

    QPiprtosap symbolYesPix, symbolModPix, symbolNoPix;
    QPiprtosap choiceYesPix, choiceNoPix;
    QPiprtosap menuPix, menuInvPix, menuBackPix, voidPix;

    bool showAll, showName, showRange, showData;
    enum listMode mode;
    struct menu *rootEntry;
    QColorGroup disabledColorGroup;
    QColorGroup inactivedColorGroup;
    QPopupMenu *headerPopup;

   private:
    int colMap[colNr];
    int colRevMap[colNr];
};

class ConfigItem : public QListViewItem {
    typedef class QListViewItem Parent;

   public:
    ConfigItem(QListView *parent, ConfigItem *after, struct menu *m, bool v) : Parent(parent, after), menu(m), visible(v), goParent(false) {
        init();
    }
    ConfigItem(ConfigItem *parent, ConfigItem *after, struct menu *m, bool v) : Parent(parent, after), menu(m), visible(v), goParent(false) {
        init();
    }
    ConfigItem(QListView *parent, ConfigItem *after, bool v) : Parent(parent, after), menu(0), visible(v), goParent(true) {
        init();
    }
    ~ConfigItem(void);
    void init(void);
#if QT_VERSION >= 300
    void okRename(int col);
#endif
    void updateMenu(void);
    void testUpdateMenu(bool v);
    ConfigList *listView() const {
        return (ConfigList *)Parent::listView();
    }
    ConfigItem *firstChild() const {
        return (ConfigItem *)Parent::firstChild();
    }
    ConfigItem *nextSibling() const {
        return (ConfigItem *)Parent::nextSibling();
    }
    void setText(colIdx idx, const QString &text) {
        Parent::setText(listView()->mapIdx(idx), text);
    }
    QString text(colIdx idx) const {
        return Parent::text(listView()->mapIdx(idx));
    }
    void setPiprtosap(colIdx idx, const QPiprtosap &pm) {
        Parent::setPiprtosap(listView()->mapIdx(idx), pm);
    }
    const QPiprtosap *piprtosap(colIdx idx) const {
        return Parent::piprtosap(listView()->mapIdx(idx));
    }
    void paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int align);

    ConfigItem *nextItem;
    struct menu *menu;
    bool visible;
    bool goParent;
};

class ConfigLineEdit : public QLineEdit {
    Q_OBJECT
    typedef class QLineEdit Parent;

   public:
    ConfigLineEdit(ConfigView *parent);
    ConfigView *parent(void) const {
        return (ConfigView *)Parent::parent();
    }
    void show(ConfigItem *i);
    void keyPressEvent(QKeyEvent *e);

   public:
    ConfigItem *item;
};

class ConfigView : public QVBox {
    Q_OBJECT
    typedef class QVBox Parent;

   public:
    ConfigView(QWidget *parent, const char *name = 0);
    ~ConfigView(void);
    static void updateList(ConfigItem *item);
    static void updateListAll(void);

    bool showAll(void) const {
        return list->showAll;
    }
    bool showName(void) const {
        return list->showName;
    }
    bool showRange(void) const {
        return list->showRange;
    }
    bool showData(void) const {
        return list->showData;
    }
   public slots:
    void setShowAll(bool);
    void setShowName(bool);
    void setShowRange(bool);
    void setShowData(bool);
   signals:
    void showAllChanged(bool);
    void showNameChanged(bool);
    void showRangeChanged(bool);
    void showDataChanged(bool);

   public:
    ConfigList *list;
    ConfigLineEdit *lineEdit;

    static ConfigView *viewList;
    ConfigView *nextView;
};

class ConfigInfoView : public QTextBrowser {
    Q_OBJECT
    typedef class QTextBrowser Parent;

   public:
    ConfigInfoView(QWidget *parent, const char *name = 0);
    bool showDebug(void) const {
        return _showDebug;
    }

   public slots:
    void setInfo(struct menu *menu);
    void saveSettings(void);
    void setSource(const QString &name);
    void setShowDebug(bool);

   signals:
    void showDebugChanged(bool);
    void menuSelected(struct menu *);

   protected:
    void symbolInfo(void);
    void menuInfo(void);
    QString debug_info(struct symbol *sym);
    static QString print_filter(const QString &str);
    static void expr_print_help(void *data, struct symbol *sym, const char *str);
    QPopupMenu *createPopupMenu(const QPoint &pos);
    void contentsContextMenuEvent(QContextMenuEvent *e);

    struct symbol *sym;
    struct menu *menu;
    bool _showDebug;
};

class ConfigSearchWindow : public QDialog {
    Q_OBJECT
    typedef class QDialog Parent;

   public:
    ConfigSearchWindow(ConfigMainWindow *parent, const char *name = 0);

   public slots:
    void saveSettings(void);
    void search(void);

   protected:
    QLineEdit *editField;
    QPushButton *searchButton;
    QSplitter *split;
    ConfigView *list;
    ConfigInfoView *info;

    struct symbol **result;
};

class ConfigMainWindow : public QMainWindow {
    Q_OBJECT

    static QAction *saveAction;
    static void conf_changed(void);

   public:
    ConfigMainWindow(void);
   public slots:
    void changeMenu(struct menu *);
    void setMenuLink(struct menu *);
    void listFocusChanged(void);
    void goBack(void);
    void loadConfig(void);
    void saveConfig(void);
    void saveConfigAs(void);
    void searchConfig(void);
    void showSingleView(void);
    void showSplitView(void);
    void showFullView(void);
    void showIntro(void);
    void showAbout(void);
    void saveSettings(void);

   protected:
    void closeEvent(QCloseEvent *e);

    ConfigSearchWindow *searchWindow;
    ConfigView *menuView;
    ConfigList *menuList;
    ConfigView *configView;
    ConfigList *configList;
    ConfigInfoView *helpText;
    QToolBar *toolBar;
    QAction *backAction;
    QSplitter *split1;
    QSplitter *split2;
};
